package com.qf.ability.gateway.sentinel;

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.qf.ability.gateway.sentinel.nacos.NacosDatasourceConfig;
import com.qf.ability.gateway.sentinel.nacos.NacosDatasourceLoader;
import com.qf.commons.core.utils.JsonUtils;
import com.qf.data.r.Codes;
import com.qf.data.r.R;
import com.qf.data.r.RUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * description: Sentinel的异常处理
 * author: Ken
 * 公众号：Java架构栈
 */
@Configuration
@EnableConfigurationProperties(NacosDatasourceConfig.class)
@Slf4j
public class SentinelExceptionHandler implements BlockRequestHandler {

    @Bean
    public void init(){
        GatewayCallbackManager.setBlockHandler(this);
    }

    @Bean
    public NacosDatasourceLoader getNacosDatasourceLoader(){
        return new NacosDatasourceLoader();
    }

    /**
     * 异常处理方法
     * @param exchange
     * @param t
     * @return
     */
    @Override
    public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
        log.debug("[gateway sentinel flow] 网关流控触发！- {}", exchange.getRequest().getURI());

        //返回对象
        R result = null;

        if (t instanceof ParamFlowException) {
            //网关流控异常
            result = RUtils.create(Codes.FLOW_ERROR);
        } else if(t instanceof DegradeException){
            //网关降级异常
            result = RUtils.create(Codes.DEGRADE_ERROR);
        } else {
            //默认服务器异常
            result = RUtils.create(Codes.FAIL);
        }

        return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                .header("content-type", "application/json;charset=utf-8")
                .bodyValue(JsonUtils.obj2Json(result));
    }
}
